gsk: Allow adding a GL texture as a node content
authorEmmanuele Bassi <ebassi@gnome.org>
Fri, 12 Aug 2016 15:44:29 +0000 (16:44 +0100)
committerEmmanuele Bassi <ebassi@gnome.org>
Tue, 18 Oct 2016 10:49:14 +0000 (11:49 +0100)
If we already have a GL texture we definitely don't want to use
gdk_cairo_draw_from_gl() to draw on a Cairo context if we're going
to take the Cairo surface to which we draw and put it into an OpenGL
texture.

gsk/gskglrenderer.c
gsk/gskrendernode.c
gsk/gskrendernode.h
gsk/gskrendernodeprivate.h

index c343f4c91c96c4cc03551fb5c80c611eeb6adee0..4d5c4f36981fe00bd3de8e48548f026e8d97bda0 100644 (file)
@@ -602,7 +602,6 @@ gsk_gl_renderer_add_render_item (GskGLRenderer           *self,
                                  RenderItem              *parent)
 {
   graphene_rect_t viewport;
-  cairo_surface_t *surface;
   GskRenderNodeIter iter;
   graphene_matrix_t mv;
   graphene_rect_t bounds;
@@ -705,22 +704,31 @@ gsk_gl_renderer_add_render_item (GskGLRenderer           *self,
       item.children = NULL;
     }
 
-  surface = gsk_render_node_get_surface (node);
-
-  /* If the node does not draw anything, we skip it */
-  if (surface == NULL && item.render_data.render_target_id == self->texture_id)
-    goto out;
-
-  /* Upload the Cairo surface to a GL texture */
-  item.render_data.texture_id = gsk_gl_driver_create_texture (self->gl_driver,
-                                                              item.size.width,
-                                                              item.size.height);
-  gsk_gl_driver_bind_source_texture (self->gl_driver, item.render_data.texture_id);
-  gsk_gl_driver_init_texture_with_surface (self->gl_driver,
-                                           item.render_data.texture_id,
-                                           surface,
-                                           self->gl_min_filter,
-                                           self->gl_mag_filter);
+  if (gsk_render_node_has_texture (node))
+    {
+      item.render_data.texture_id = gsk_render_node_get_texture (node);
+    }
+  else if (gsk_render_node_has_surface (node))
+    {
+      cairo_surface_t *surface = gsk_render_node_get_surface (node);
+
+      /* Upload the Cairo surface to a GL texture */
+      item.render_data.texture_id = gsk_gl_driver_create_texture (self->gl_driver,
+                                                                  item.size.width,
+                                                                  item.size.height);
+      gsk_gl_driver_bind_source_texture (self->gl_driver, item.render_data.texture_id);
+      gsk_gl_driver_init_texture_with_surface (self->gl_driver,
+                                               item.render_data.texture_id,
+                                               surface,
+                                               self->gl_min_filter,
+                                               self->gl_mag_filter);
+    }
+  else
+    {
+      /* If the node does not draw anything, we skip it */
+      if (item.render_data.render_target_id == self->texture_id)
+        goto out;
+    }
 
   /* Create the vertex buffers holding the geometry of the quad */
   {
index 1ec296e6f3339c88a5653e1184424eff3a33dc8e..c39480ee130d2572b2a363c8d6fbab89df92833e 100644 (file)
@@ -1186,6 +1186,48 @@ gsk_render_node_update_world_matrix (GskRenderNode *node,
     gsk_render_node_update_world_matrix (child, TRUE);
 }
 
+gboolean
+gsk_render_node_has_surface (GskRenderNode *node)
+{
+  g_return_val_if_fail (GSK_IS_RENDER_NODE (node), FALSE);
+
+  return node->surface != NULL;
+}
+
+gboolean
+gsk_render_node_has_texture (GskRenderNode *node)
+{
+  g_return_val_if_fail (GSK_IS_RENDER_NODE (node), FALSE);
+
+  return node->texture_id != 0;
+}
+
+int
+gsk_render_node_get_texture (GskRenderNode *node)
+{
+  g_return_val_if_fail (GSK_IS_RENDER_NODE (node), 0);
+
+  return node->texture_id;
+}
+
+/**
+ * gsk_render_node_set_texture:
+ * @node: a #GskRenderNode
+ * @texture_id: the object id of a GL texture
+ *
+ * Associates a @texture_id to a #GskRenderNode.
+ *
+ * Since: 3.22
+ */
+void
+gsk_render_node_set_texture (GskRenderNode *node,
+                             int            texture_id)
+{
+  g_return_if_fail (GSK_IS_RENDER_NODE (node));
+
+  node->texture_id = texture_id;
+}
+
 /*< private >
  * gsk_render_node_get_surface:
  * @node: a #GskRenderNode
index afeab20219e688421f51a26267a594ad51eec4f1..d597ea7163b35ba7553f708b41ab1da2da3203e8 100644 (file)
@@ -119,6 +119,10 @@ void                    gsk_render_node_set_blend_mode          (GskRenderNode *
 GDK_AVAILABLE_IN_3_22
 GskBlendMode            gsk_render_node_get_blend_mode          (GskRenderNode *node);
 
+GDK_AVAILABLE_IN_3_22
+void                    gsk_render_node_set_texture             (GskRenderNode *node,
+                                                                 int            texture_id);
+
 GDK_AVAILABLE_IN_3_22
 int                     gsk_render_node_get_scale_factor        (GskRenderNode *node);
 
index 85cb2b839eabb6c9659684ffcb4814dab9bb0f1c..84ee2f08fdfefd6297a35a33ced474884326f9a7 100644 (file)
@@ -35,9 +35,12 @@ struct _GskRenderNode
   /* Tag updated when adding/removing children */
   gint64 age;
 
-  /* The contents of the node */
+  /* The contents of the node as a Cairo surface */
   cairo_surface_t *surface;
 
+  /* The contents of the node as a GL surface */
+  int texture_id;
+
   /* Paint opacity */
   double opacity;
 
@@ -82,6 +85,11 @@ double gsk_render_node_get_opacity (GskRenderNode *node);
 
 cairo_surface_t *gsk_render_node_get_surface (GskRenderNode *node);
 
+int gsk_render_node_get_texture (GskRenderNode *node);
+
+gboolean gsk_render_node_has_surface (GskRenderNode *node);
+gboolean gsk_render_node_has_texture (GskRenderNode *node);
+
 GskRenderNode *gsk_render_node_get_toplevel (GskRenderNode *node);
 
 void gsk_render_node_update_world_matrix (GskRenderNode *node,